Skip to content

Python: Add A2A hosting helpers#7050

Open
eavanvalkenburg wants to merge 3 commits into
microsoft:mainfrom
eavanvalkenburg:hosting-a2a-helpers
Open

Python: Add A2A hosting helpers#7050
eavanvalkenburg wants to merge 3 commits into
microsoft:mainfrom
eavanvalkenburg:hosting-a2a-helpers

Conversation

@eavanvalkenburg

Copy link
Copy Markdown
Member

Motivation & Context

A2A hosting needs the same helper-first boundary as the other hosting protocol packages: protocol conversion should be reusable without selecting a web framework or hiding native SDK lifecycle behavior. This adds the conversion seam needed to host Agent Framework agents through the A2A SDK while leaving applications in control of executors, tasks, queues, stores, routes, authentication, and deployment.

Description & Review Guide

  • What are the major changes? Adds the alpha agent-framework-hosting-a2a package with a2a_to_run(...) and a2a_from_run(...), focused conversion tests, package/workspace metadata, and concrete hosting-spec documentation. Updates both existing A2A server samples to compose those helpers with an application-owned native A2A AgentExecutor.
  • What is the impact of these changes? Applications can translate native A2A messages and Agent Framework responses or stream updates without adopting a host registry, channel abstraction, executor wrapper, or prescribed web framework. The existing beta agent-framework-a2a package remains unchanged.
  • What do you want reviewers to focus on? The two-helper package boundary, A2A part fidelity, and whether the samples keep task/session/streaming policy visibly application-owned.

Related Issue

Fixes #6591

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607
Copilot AI review requested due to automatic review settings July 10, 2026 13:17
@giles17 giles17 added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Jul 10, 2026
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/hosting-a2a/agent_framework_hosting_a2a
   _conversion.py550100% 
TOTAL44192526588% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
8852 33 💤 0 ❌ 0 🔥 2m 23s ⏱️

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 5 | Confidence: 84%

✓ Correctness

The PR adds a clean, focused conversion package with two helpers (a2a_to_run and a2a_from_run) that correctly translate between native A2A SDK types and Agent Framework types. I verified the Content, Message, AgentResponse, AgentResponseUpdate, and AgentRunArgs type definitions against the conversion code. All field accesses are valid, the data URI round-trip (base64 encode in from_data → decode in a2a_from_run) is correct, protobuf metadata is handled properly via MessageToDict, edge cases (empty messages, empty text, invalid URIs, invalid base64) are covered by tests, and the sample code correctly composes the helpers with native A2A SDK constructs. No correctness issues found.

✓ Security Reliability

The new agent-framework-hosting-a2a conversion library is well-designed with proper input validation, safe base64 handling (using validate=True), and clear error messages. The library code itself has no security or reliability issues. The two sample executors expose raw exception messages to A2A clients via str(exc), which could leak internal details (file paths, connection strings, stack context) from unexpected exceptions caught by the broad except Exception clause. This is a low-severity concern since these are samples with existing production-readiness caveats in the README.

✓ Test Coverage

The new agent-framework-hosting-a2a package has good test coverage for the main conversion paths (all four A2A part types inbound, text/URI/data outbound, streaming updates, empty text, invalid data URIs). Two notable gaps remain: (1) the fallthrough/unsupported-type warning-and-skip branches in both a2a_to_run and a2a_from_run are untested, and (2) a2a_from_run returning an empty list (e.g., only user-role messages in an AgentResponse) is not covered. These are defensive paths that, by comparison, the sibling hosting-responses package does test for unknown input types.

✓ Failure Modes

The new agent-framework-hosting-a2a package provides clean, side-effect-free conversion between native A2A SDK types and Agent Framework run types. The library code handles edge cases defensively: empty messages raise ValueError, unsupported part types are logged and omitted, invalid data URIs and base64 are rejected with clear errors, and empty text strings are preserved correctly. The AgentResponseUpdate.contents field normalizes None to [] in its constructor (line 2982 of _types.py), so the for content in item.contents iteration in a2a_from_run is safe. The sample executor code uses logging-only error handling in its except Exception block, but this is explicitly application-owned sample code per the PR rationale, not a library concern. No concrete failure-mode bugs were found in the library conversion code.

✓ Design Approach

I found one non-blocking design gap in the new helper boundary: a2a_from_run(...) drops Agent Framework message/update-level metadata, so the conversion is less faithful than the existing A2A executor pattern even though the core types and prior implementation both preserve that metadata.

Suggestions

  • Both sample AppAgentExecutor.execute() methods (a2a_server.py:108, agent_framework_to_a2a.py:88) forward str(exc) to the A2A client from a broad except Exception handler. Unexpected errors (DB failures, auth errors, etc.) may expose internal details to untrusted calers. Consider replacing with a generic message like "Agent execution failed" since logger.exception already preserves full diagnostics server-side.
  • Add tests for the unsupported-type fallthrough branches: (1) pass a Content with an unsupported type (e.g., function_call) to a2a_from_run and assert an empty list is returned, and (2) pass a mix of supported and unsupported A2A parts to a2a_to_run and verify unsupported ones are gracefully omitted. The sibling hosting-responses tests cover analogous unknown-type paths.

Automated review by eavanvalkenburg's agents

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new alpha Python package, agent-framework-hosting-a2a, that provides a helper-first conversion seam between native A2A SDK messages/parts and Agent Framework run inputs/outputs, and updates existing A2A hosting samples/docs to use that seam while keeping SDK lifecycle and web framework ownership in application code.

Changes:

  • Added python/packages/hosting-a2a with a2a_to_run(...) and a2a_from_run(...) conversion helpers plus focused unit tests and package metadata.
  • Updated both A2A hosting server samples to compose a native A2A AgentExecutor with the new conversion helpers and shared hosting state (AgentState).
  • Updated workspace metadata and documentation/specs to include the new hosting-a2a helper package.

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
python/uv.lock Adds agent-framework-hosting-a2a as a workspace member and locks its editable metadata/deps.
python/pyproject.toml Registers agent-framework-hosting-a2a in the Python workspace deps list.
python/PACKAGE_STATUS.md Marks agent-framework-hosting-a2a as alpha.
python/AGENTS.md Adds the new package to the Python package index.
python/packages/hosting-a2a/pyproject.toml New package definition, dependencies, and standard tooling config.
python/packages/hosting-a2a/README.md Documents the helper-only boundary and example composition.
python/packages/hosting-a2a/AGENTS.md Defines public API and boundary expectations for contributors.
python/packages/hosting-a2a/LICENSE Adds MIT license text for the new package.
python/packages/hosting-a2a/agent_framework_hosting_a2a/init.py Exposes a2a_to_run / a2a_from_run and version.
python/packages/hosting-a2a/agent_framework_hosting_a2a/_conversion.py Implements A2A↔Agent Framework conversion logic.
python/packages/hosting-a2a/agent_framework_hosting_a2a/py.typed Marks the package as typed for consumers.
python/packages/hosting-a2a/tests/hosting_a2a/test_conversion.py Adds unit tests covering supported parts and validation.
python/samples/04-hosting/a2a/requirements.txt Updates sample dev installs to include hosting + hosting-a2a instead of agent-framework-a2a.
python/samples/04-hosting/a2a/README.md Clarifies boundary/ownership and session-key guidance for multi-replica production.
python/samples/04-hosting/a2a/a2a_server.py Refactors sample to a native A2A executor + conversion helpers + AgentState.
python/samples/04-hosting/a2a/agent_framework_to_a2a.py Same refactor pattern for the second server sample.
docs/specs/002-python-hosting-channels.md Documents the new helper package in the hosting channels spec.

Comment thread python/samples/04-hosting/a2a/agent_framework_to_a2a.py
Comment thread python/samples/04-hosting/a2a/a2a_server.py
@eavanvalkenburg eavanvalkenburg marked this pull request as ready for review July 10, 2026 13:36
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 5 | Confidence: 86%

✓ Correctness

The conversion helpers in _conversion.py are correctly implemented. Type usage (AgentRunArgs, Content factory methods, AgentState) aligns with their definitions. The match/case patterns handle edge cases properly with appropriate guards (None checks), error messages are clear, and data URI round-tripping is correct. The tests provide good coverage of the conversion logic. No correctness bugs found in the library code. The sample executors are functional demonstrations that compose the helpers with native A2A SDK constructs as intended by the PR rationale.

✓ Security Reliability

The conversion library (_conversion.py) is well-structured from a security/reliability perspective: it validates data URIs before decoding, uses base64.b64decode with validate=True, raises clear errors for invalid input, and properly handles empty/missing content. The library explicitly documents its trust boundary (parse/render only; no auth/access control). The only notable concern is in the sample code where raw exception messages are forwarded to the remote A2A client, which could disclose internal implementation details. However, as these are explicitly samples and the README already calls out that production applications need different practices, this is low severity.

✓ Test Coverage

The test file provides solid coverage of the happy paths and key error conditions for both conversion helpers. The main gap is that the graceful-degradation behavior for unsupported content types in a2a_from_run (silently omitting types like 'function_call' or 'error' with a warning) has no test. Since Agent Framework agents commonly produce these content types (tool calls, errors), verifying this omission behavior prevents regressions if the match statement is refactored.

✓ Failure Modes

The conversion library code is well-structured with appropriate error boundaries. The two helper functions (a2a_to_run and a2a_from_run) are side-effect-free and raise on invalid inputs. The sample executors handle exceptions by transitioning tasks to FAILED state. No high-severity silent-failure or data-loss issues identified in the library code. The existing unresolved review comments on the samples (streaming-only artifact path) are noted and not duplicated here.

✓ Design Approach

I found one blocking design issue. The new a2a_from_run(...) -> list[Part] contract, and the test that locks it in, flatten completed Agent Framework responses into a single part list. That makes the helper incapable of preserving the per-message boundaries and message-level metadata that the existing A2A executor preserves today.

Suggestions

  • In both sample executors (a2a_server.py:108, agent_framework_to_a2a.py:88), raw exception text is sent to the remote A2A client via Part(text=str(exc)). While acceptable in sample code, consider using a generic message (e.g., 'Internal agent error') to avoid accidentally modeling information disclosure for production copy-paste.

Automated review by eavanvalkenburg's agents

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5d6987cd-1b67-4ba1-8b54-3c50da6e7607
@eavanvalkenburg

Copy link
Copy Markdown
Member Author

Addressed the latest automated review feedback in eab0bfc:

  • Both samples now log full exceptions server-side but return a generic failure message to A2A clients.
  • Conversion tests now cover unsupported inbound parts, unsupported Agent Framework content, and user-only responses.
  • The helper documentation now makes the intentional boundary explicit: a2a_from_run(...) preserves content-level metadata and returns parts in message order, while applications own A2A message/artifact grouping, boundaries, IDs, and message-level metadata. Keeping list[Part] avoids introducing a higher-level executor or delivery abstraction into this conversion-only package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Add A2A hosting conversion helpers

3 participants